import threading
import json
import requests
import socket
import os

# TCP服务器
serversocket = socket.socket(
    socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
serversocket.bind(("127.0.0.1", 20054))
serversocket.listen(50)


ffmpeg_url = ""
def getBilibiliVideoURL(id:str):
    url_id = ""
    if(id[0].lower() == 'a'):
        url_id = 'aid=' + id[2:]
    else:
        url_id = 'bvid=' + id
    a = requests.session()
    a.headers["Accept"] = "*/*"
    a.headers["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
    res = a.get('http://api.bilibili.com/x/player/pagelist?' + url_id)
    j_cid = res.json()
    if(j_cid["code"] == 0):
        cid = j_cid["data"][0]["cid"]
        if(id[0].lower() == 'a'):
            url_id = 'avid=' + id[2:]
        else:
            url_id = 'bvid=' + id
        res = a.get("http://api.bilibili.com/x/player/playurl?" + url_id + "&cid=" + str(cid) + "&qn=32&fnval=1&fnver=0&fourk=0")
        j_vid = res.json()
        if(j_vid["code"] == 0):
            return(j_vid["data"]["durl"][0]["url"])
    return ""

def ffmpeg_task():
    path_pref = r'ffmpeg -re -headers "referer: https://www.bilibili.com" -user_agent "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" -i "'
    path_append = r'" -vf scale=w=320:h=240:force_original_aspect_ratio=decrease,fps=24 -c:v mpeg1video -b:v 400k -maxrate 600k -c:a mp2 -format mpeg -ar 48000 -b:a 128k -ac 2 -f mpeg tcp://127.0.0.1:20055?listen'
    print(os.system(path_pref + ffmpeg_url + path_append))


def searchAndPlay(id):
    global ffmpeg_url
    ffmpeg_url = getBilibiliVideoURL(id)
    if(ffmpeg_url == ""):
        #无法获取视频链接
        return False
    os.system("killall ffmpeg")
    thread_ffmpeg = threading.Thread(target=ffmpeg_task,daemon=True)
    thread_ffmpeg.start()
    return True


def thread_tcp_server(clientsocket, addr):
    while True:
        try:
            clientsocket.settimeout(60)
            buffer=[clientsocket.recv(10)]    #一开始的部分,用于等待传输开始,避免接收不到的情况.
            if buffer[0] in (0,-1):    #返回0,-1代表出错
                return False
            clientsocket.settimeout(1)
            while True:    #循环接收
                try:
                    data=clientsocket.recv(256)    #接收1024字节
                    if(data == b""):
                        return
                    buffer.append(data)    #拼接到结果中
                except:    #如果没有数据了
                    break    #退出循环
            clientsocket.settimeout(60)
            r =  b"".join(buffer).decode("utf-8")    #编码并返回
            if(r == b""):
                raise "Error"
            send = {
                "method": "ok",
                "payload": ""
            }
            recvjson = json.loads(r)
            if (recvjson["method"] == "bilibili"):
                send["payload"] = searchAndPlay(recvjson["payload"])
            msg = json.dumps(send)
            msg += '\n'
            print(msg)
            clientsocket.send(msg.encode('utf-8'))    
        except Exception as e:
            print(e)
            print("行号",e.__traceback__.tb_lineno)
            try:
                print("Closing")
                clientsocket.close()
                print("Done")
            except:
                return
            return

def thread_tcp_accepter():
    while True:
        try:            
            new_socket, addr = serversocket.accept()
            print("new socket")
            thread_server=threading.Thread(target=thread_tcp_server,args=(new_socket,addr), daemon=True)
            thread_server.start()
        except Exception as e:
            print(e)
            print(repr(e))

thread_tcp_accepter()